<?php
/**
 * Created by PhpStorm
 * User: Jhinwy
 * Date: 5/20/24
 * Time: 4:52 PM
 */

namespace App\Services;

use App\Models\WechatCorp;
use Cium\WeWorkApi\utils\Utils;
use Cium\WeWorkApi\callback\WXBizMsgCrypt;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class CorpService
{

    const REDIS_CORP_WECHAT_SUITE_ACCESS_TOKEN = 'corp_wechat_suite_access_token';
    const REDIS_CORP_WECHAT_TICKET             = 'corp_wechat_ticket';


    /**
     * 应用信息
     *
     * @var mixed
     */
    protected $corpId;
    protected $aesKey;
    protected $suiteId;
    protected $suiteToken;
    protected $suiteSecret;

    protected $api = [];

    protected $headers = ['Content-Type' => 'application/json'];


    public function __construct()
    {
        $this->corpId      = env('CORP_WECHAT_CORP_ID', '');
        $this->aesKey      = env('CORP_WECHAT_ENCODING_AES_KEY', '');
        $this->suiteId     = env('CORP_WECHAT_SUITE_ID', '');
        $this->suiteToken  = env('CORP_WECHAT_SUITE_TOKEN', '');
        $this->suiteSecret = env('CORP_WECHAT_SUITE_SECRET', '');

        $this->api = config('corp_wechat');
    }


    /**
     * 获取授权企业列表
     *
     * @param $params
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function getCorpList($params)
    {
        $pageSize = $params['page_size'] ?? 50;

        return WechatCorp::query()->select(
            'id', 'corp_id', 'corp_name', 'corp_scale', 'corp_sub_industry', 'agentid',
            'name', 'userid', 'created_at', 'updated_at'
        )->paginate($pageSize);
    }


    /**
     * 获取所有企业信息
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function getAll()
    {
        return WechatCorp::query()->select('id', 'corp_id', 'corp_name')->get();
    }


    /**
     * 事件回调信息
     *
     * @param $msgSignature
     * @param $timestamp
     * @param $nonce
     * @param $echostr
     * @param string $contents
     * @param string $returnStr
     * @return int|string
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function eventCallback($msgSignature, $timestamp, $nonce, $echostr, $contents = '', &$returnStr = '')
    {
        Log::info('企业微信事件回调', [$msgSignature, $timestamp, $nonce, $echostr, $contents]);

        if ($contents) {
            $wxcpt      = new WXBizMsgCrypt($this->suiteToken, $this->aesKey, $this->suiteId);
            $xmlContent = '';
            $errCode    = $wxcpt->DecryptMsg($msgSignature, $timestamp, $nonce, $contents, $xmlContent);
            if ($errCode == 0) {
                $data = Utils::Xml2Array($xmlContent);
                Log::info('代开发授权&ticket===>', $data);
                switch ($data['InfoType'] ?? '') {
                    case 'create_auth' :
                        $this->setAuthCode($data['AuthCode'] ?? '');
                        break;
                    case 'suite_ticket' :
                        $this->setTicket($data['SuiteTicket'] ?? '');
                        break;
                    case 'cancel_auth' :
                        $this->delCorp($data['AuthCorpId'] ?? '');
                        break;
                }

                return 'success';
            }
        }

        $wxcpt   = new WXBizMsgCrypt($this->suiteToken, $this->aesKey, $this->corpId);
        $errCode = $wxcpt->VerifyURL($msgSignature, $timestamp, $nonce, $echostr, $returnStr);

        return $errCode;
    }


    /**
     * 设置ticket
     *
     * @param $suiteTicket
     */
    public function setTicket($suiteTicket)
    {
        Cache::put(self::REDIS_CORP_WECHAT_TICKET, $suiteTicket);
    }


    /**
     * 获取ticket
     *
     * @return mixed
     */
    public function getTicket()
    {
        return Cache::get(self::REDIS_CORP_WECHAT_TICKET);
    }


    /**
     * 获取应用token
     *
     * @return mixed|string
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getAccessToken()
    {
        if ($accessToken = Cache::get(self::REDIS_CORP_WECHAT_SUITE_ACCESS_TOKEN)) {

            return $accessToken;
        }

        try {
            $body     = [
                'headers'            => $this->headers,
                RequestOptions::JSON => [
                    'suite_id'     => $this->suiteId,
                    'suite_secret' => $this->suiteSecret,
                    'suite_ticket' => $this->getTicket()
                ]
            ];
            $client   = new Client();
            $response = $client->request('POST', $this->api['suite_access_token'], $body);
            if ($response->getStatusCode() != 200) {
                throw new \Exception('请求失败！');
            }
            $contents = $response->getBody()->getContents();
            Log::info('获取代开发应用Token信息：', [$contents]);
            $data        = json_decode($contents, true);
            $accessToken = $data['suite_access_token'] ?? '';
            $expiresIn   = $data['expires_in'] ?? 0;
            if (!$accessToken || !$expiresIn) {
                throw new \Exception('应用token不存在');
            }
            Cache::put(self::REDIS_CORP_WECHAT_SUITE_ACCESS_TOKEN, $accessToken, $expiresIn);

            return $accessToken;
        } catch (\Exception $exception) {
            Log::error('获取代开发应用token失败：' . $exception->getMessage());

            return '';
        }
    }


    /**
     * 设置授权码
     *
     * @param $authCode
     * @return bool
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function setAuthCode($authCode)
    {
        try {
            $body     = [
                'headers'            => $this->headers,
                RequestOptions::JSON => [
                    'auth_code' => $authCode,
                ]
            ];
            $client   = new Client();
            $response = $client->request(
                'POST',
                sprintf($this->api['permanent_code'], $this->getAccessToken()),
                $body
            );
            if ($response->getStatusCode() != 200) {
                throw new \Exception('请求失败！');
            }
            // 授权信息
            $contents       = $response->getBody()->getContents();
            $data           = json_decode($contents, true);
            $permanent_code = $data['permanent_code'] ?? '';
            Log::info('获取代开发应用授权码信息：', [$contents]);
            if (!$permanent_code) {
                throw new \Exception('获取授权码失败');
            }

            $auth_corp_info    = $data['auth_corp_info'] ?? [];
            $auth_info         = $data['auth_info'] ?? [];
            $auth_user_info    = $data['auth_user_info'] ?? [];
            $corpid            = $auth_corp_info['corpid'] ?? '';
            $corp_name         = $auth_corp_info['corp_name'] ?? '';
            $corp_scale        = $auth_corp_info['corp_scale'] ?? '';
            $corp_industry     = $auth_corp_info['corp_industry'] ?? '';
            $corp_sub_industry = $auth_corp_info['corp_sub_industry'] ?? '';
            $agentid           = $auth_info['agent'][0]['agentid'] ?? 0;
            $name              = $auth_info['agent'][0]['name'] ?? 0;
            $userid            = $auth_user_info['userid'] ?? '';
            $open_userid       = $auth_user_info['open_userid'] ?? '';

            // 保存授权企业信息
            $corp                    = WechatCorp::query()->firstOrNew(['corp_id' => $corpid]);
            $corp->corp_name         = $corp_name;
            $corp->corp_scale        = $corp_scale;
            $corp->corp_industry     = $corp_industry;
            $corp->corp_sub_industry = $corp_sub_industry;
            $corp->permanent_code    = $permanent_code;
            $corp->agentid           = $agentid;
            $corp->name              = $name;
            $corp->userid            = $userid;
            $corp->open_userid       = $open_userid;
            $corp->save();

            return true;
        } catch (\Exception $exception) {
            Log::error('设置代开发企业永久授权码失败：' . $exception->getMessage());

            return false;
        }
    }


    /**
     * 删除授权企业
     *
     * @param $corpId
     */
    public function delCorp($corpId)
    {
        WechatCorp::query()->where('corp_id', $corpId)->delete();

        // Cache::forget(self::REDIS_REPLACE_WORK_WECHAT_REPLACE_KF_MSG_CURSOR . $corpId);
        // Cache::forget(self::REDIS_REPLACE_WORK_WECHAT_REPLACE_ACCESS_TOKEN . $corpId);
    }
}
